import json
import os
import re
import time
from ExportLayuiReport.ExportReport import ExportReport as ExportLayuiReport
from config.setting import ReportDir
from libs.helper import get_token
from libs.tools import Notification
from models.orders_info import orders_info
from models.RedisOperation import RedisClient
from models.base import db, session_scope, shutdown_session
from models.captcha import captcha
from models.orders import Orders
from models.paragraphs import Paragraphs
from models.report_info import report_info
from models.report_source_info import report_source_info
from models.sentence import Sentence
from models.sentence_detail import sentence_detail
from models.user import User
from oss.alioss import AliOss
from MakeDocumentReport import MakeDocumentReport
from taobao_api.update_order_status import Logistics_Dummy_Send
from models.taobao_orders import taobao_orders


class MakeReport(object):

    def __init__(self):
        self.r = RedisClient()

    def insertSuggest(self, order_number):
        sentences = Sentence()
        info = sentences.get_similar_sentences(order_number)
        for item in info:
            self.r.db.lpush('suggest', f'{item.order_number}#{item.sentence_index}#{item.content}')
        self.r.db.lpush('report_dev', order_number)

    def PaperData(self, order_number):
        paragraph = Paragraphs()
        paragraph_indexs = paragraph.get_indexs(order_number)
        sentence_model = Sentence()
        report_text = []
        for index in paragraph_indexs:
            info = []
            report_sentences = sentence_model.get_sentence(index[0], order_number)
            if report_sentences:
                for sentences in report_sentences:
                    info.append(
                        {
                            'similar': sentences.is_similar,
                            'context': self.format(sentences.content),
                            'index': sentences.sentence_index,
                            'rate': int(sentences.rate * 100),
                            'is_author': sentences.is_author
                        }
                    )
            report_text.append(
                {
                    'paragraph': index[0],
                    'sentence': info
                }
            )
        paragraphs = paragraph.get_paragraphs(order_number)
        return report_text, paragraphs

    def base_info(self, order_number):
        paragraph = Paragraphs()
        paragraph_indexs = paragraph.get_indexs(order_number)
        sentence_model = Sentence()
        similar_sentence = sentence_detail()
        sentence_sum = 0
        except_author_sentence_sum = 0
        similar_sentence_sum = 0
        report_text = []
        internet, local = similar_sentence.internetData(order_number)
        for index in paragraph_indexs:
            info = []
            report_sentences = sentence_model.get_sentence(index[0], order_number)
            if report_sentences:
                for sentences in report_sentences:
                    info.append(
                        {
                            'similar': sentences.is_similar,
                            'context': sentences.content,
                            'index': sentences.sentence_index,
                            'is_author': sentences.is_author
                        }
                    )
                    sentence_sum += 1
                    if sentences.is_similar == 1:
                        if sentences.is_author == 1:
                            if 0.7 <= sentences.rate < 0.8:
                                similar_sentence_sum += len(sentences.content) * sentences.rate
                            else:
                                similar_sentence_sum += len(sentences.content)
                        else:
                            if 0.7 <= sentences.rate < 0.8:
                                except_author_sentence_sum += len(sentences.content) * sentences.rate
                                similar_sentence_sum += len(sentences.content) * sentences.rate
                            else:
                                except_author_sentence_sum += len(sentences.content)
                                similar_sentence_sum += len(sentences.content)
                    if sentences.is_similar == 2:
                        similar_sentence_sum += int(len(sentences.content) * 0.5)
            report_text.append(
                {
                    'paragraph': index[0],
                    'sentence': info
                }
            )
        info = db.query(Orders).filter_by(order_number=order_number).first()
        try:
            rate = str(round(similar_sentence_sum / info.char_sum * 100, 2))
            except_author_rate = str(round(except_author_sentence_sum / info.char_sum * 100, 2))
        except ZeroDivisionError:
            rate = '0'
            except_author_rate = '0'
        if order_number[0:2] == '99':
            with session_scope() as session:
                session.query(report_info).filter_by(order_number=order_number).update({
                    'sentence_count': int(str(sentence_sum)),
                    'paragraph_count': len(paragraph_indexs),
                    'except_author_rate': except_author_rate,
                    'total_rate': rate
                })
                session.commit()
            with session_scope() as session:
                for item in internet[0:20]:
                    report_source_model = report_source_info()
                    report_source_model.order_number = order_number
                    report_source_model.source = item['source']
                    report_source_model.rate = item['rate']
                    report_source_model.source_type = 'internet'
                    session.add(report_source_model)
                for item in local[0:20]:
                    report_source_model = report_source_info()
                    report_source_model.order_number = order_number
                    report_source_model.source = item['source']
                    report_source_model.rate = item['rate']
                    report_source_model.source_type = 'local'
                    session.add(report_source_model)
                session.commit()
        return {
            'captcha': get_token(),
            'title': self.format(info.title),
            'author': self.format(info.author),
            'char_sum': info.char_sum,
            'paragraphs': len(paragraph_indexs),
            'submit_time': info.create_datetime,
            'sentence_sum': str(sentence_sum),
            'rate': rate,
            'except_author_rate': except_author_rate,
            'text_content': report_text,
            'internet': internet,
            'local': local
        }

    def is_chinese(self, chr):
        return len(chr.encode('utf8')) > len(chr)

    def SimilarData(self, order_number):
        sentence_model = Sentence()
        similar_sentence_model = sentence_detail()
        similar_sentences = sentence_model.get_similar_sentences(order_number)
        similar_data = {}

        for similar_sentence in similar_sentences:
            sentence_report = similar_sentence_model.get_top_rate(order_number, similar_sentence.check_id)
            sentence_suggest = sentence_model.sentence_suggest(order_number, similar_sentence.sentence_index)
            similar_list = []
            for item in sentence_report:
                title = item.title
                if item.source == '大学生论文联合对比库':
                    if not self.is_chinese(item.title) or len(item.title) < 4 or '查重' in item.title:
                        title = '大学生论文联合对比库'
                info = {
                    'origin_sentence': self.format(item.original_content),
                    'similar_content': self.format(item.similar_content),
                    'title': self.format(title),
                    'author': self.format(item.author),
                    'source': self.format(item.source),
                    'rate': int(item.rate * 100)
                }
                similar_list.append(info)
            similar_data[similar_sentence.sentence_index] = {}
            similar_data[similar_sentence.sentence_index]['data'] = similar_list
            similar_data[similar_sentence.sentence_index]['suggest'] = sentence_suggest
        return similar_data

    def create_ScatterDiagram(self, report, order_number):
        similar_sentence = sentence_detail()
        sentence = Sentence()
        max_x = sentence.sentence_count(order_number)
        orange_data, red_data = similar_sentence.top_rate(order_number)
        report.create_ScatterDiagram(orange_data, red_data, max_x)

    def update_captcha(self, base_info, ):
        with session_scope() as session:
            captcha_model = captcha()
            captcha_model.captcha_number = base_info['captcha']
            captcha_model.title = base_info['title']
            captcha_model.author = base_info['author']
            captcha_model.char_sum = base_info['char_sum']
            captcha_model.create_time = base_info['submit_time']
            captcha_model.similar_rate = base_info['except_author_rate']
            session.add(captcha_model)
            session.commit()

    def create_paper_html(self, report, base_info, order_number):
        report_text, paragraphs = self.PaperData(order_number)
        similar_data = self.SimilarData(order_number)
        info = base_info.copy()
        info.pop('local')
        info.pop('internet')
        info.pop('text_content')
        report.create_paper_html(report_text, similar_data, paragraphs, order_number, info)

    def create_barcode(self, report, order_number):
        sentence = Sentence()
        report.create_barcode(sentence.sentence_codebar(order_number))

    def create_assess_html(self, report, order_number, base_info):
        similar_sentence = sentence_detail()
        internet, local = similar_sentence.internetData(order_number)
        report.create_assess_html(local=local, internet=internet, view_info=base_info)

    def create_simple_pdf_html(self, report, order_number, base_info):
        similar_sentence = sentence_detail()
        internet, local = similar_sentence.internetData(order_number)
        report.create_simple_pdf_html(local=local, internet=internet, view_info=base_info)

    def create_report_html(self, report, base_info):
        report.create_report_html(base_info)

    def create_pdf_html(self, report, base_info):
        report.create_pdf_html(base_info['text_content'], base_info['local'], base_info['internet'], base_info)

    def upload_oss(self, order_number, base_info):
        with session_scope() as session:
            session.query(orders_info).filter(orders_info.order_number == order_number).update(
                {'completed': 1, 'similar_rate': base_info['except_author_rate']})
            session.query(report_info).filter(report_info.order_number == order_number).update(
                {'completed': 1})
            session.commit()
        return True

    def format(self, data):
        try:
            str = data.strip().replace('\\', '\\\\').replace('\'', '\\\''). \
                replace('\"', '\\\"').replace('\r', '').replace('\r', '') \
                .replace('\n', '').replace('\t', '').replace('\r', '').replace('\f', '').replace('\v', '')
        except:
            str = ''
        return str

    def count_zh(self, str):
        count = 0
        zh = ''
        for s in str:
            if '\u4e00' <= s <= '\u9fa5':
                count += 1
                zh += s
        return count

    def getSingleAuthor(self, authors):
        res = []
        author_list = re.split("[， ；;,、]", authors.strip())
        for item in author_list:
            if self.count_zh(item) > 1:
                res.append(item)
        return res

    def getAuthorSource(self, order_number):
        article_info = db.query(orders_info).filter_by(order_number=order_number).first()
        authors = article_info.author
        if self.count_zh(authors) < 2:
            return False
        author_list = self.getSingleAuthor(authors)
        sentence_model = Sentence()
        similar_sentences = sentence_model.get_similar_sentences(order_number)
        # with session_scope() as session:
        for sentence in similar_sentences:
            # similar_author = sentence.author
            sources = db.query(sentence_detail).filter_by(order_number=sentence.order_number).filter_by(
                check_id=sentence.check_id).filter_by(rate=sentence.rate).all()
            is_author = 0
            for item in sources:
                if item.author != '佚名' and item.author != '' and is_author == 0:
                    for author in author_list:
                        if author in item.author and is_author == 0:
                            db.query(Sentence).filter(
                                Sentence.order_number == sentence.order_number).filter(
                                Sentence.check_id == sentence.check_id).update(
                                {'is_author': 1})
                            is_author = 1
        db.commit()

    @shutdown_session
    def makeLayuiReport(self, order_number):
        report = ExportLayuiReport(order_number)
        report.create_report_directory()
        self.getAuthorSource(order_number)
        base_info = self.base_info(order_number)
        self.create_paper_html(report, base_info, order_number)
        self.create_ScatterDiagram(report, order_number)
        self.create_barcode(report, order_number)
        self.create_assess_html(report, order_number, base_info)
        self.create_simple_pdf_html(report, order_number, base_info)
        self.create_pdf_html(report, base_info)
        self.alter(ReportDir + order_number + '/htmls/js/data.js', '\\u', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-3\\"\\\\h\\\\z\\', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-5\\"\\\\h\\\\z\\', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-1\\"\\\\h\\\\z\\', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-4\\"\\\\h\\\\z\\', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-2\\"\\\\h\\\\z\\', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-3\\"\\\\h\\', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-5\\"\\\\h\\', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-4\\"\\\\h\\', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-1\\"\\\\h\\', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-2\\"\\\\h\\', '')
        self.alter(ReportDir + order_number + '/htmls/js/data.js', 'TOC\\\\o\\"1-2\\"\\\\h\\', '')
        # self.alter(ReportDir + order_number + '/htmls/js/data.js', '\\", "', '')
        # report.zip_report()
        self.update_captcha(base_info)
        # self.logistics(order_number)
        # if order_number[0:2] == '99':
        #     self.notification(order_number, base_info['rate'])
        self.upload_oss(order_number, base_info)

    def run_test(self, order_number):
        self.makeLayuiReport(order_number)

    def upload_oss_singe(self, order_number):
        oss = AliOss(order_number)
        oss.upload(ReportDir + order_number + '.zip')
        # db.query(orders_info).filter(orders_info.order_number == order_number).update({'completed': 1, 'similar_rate': base_info['rate']})
        # db.commit()
        # os.remove("Report/samereport_" + order_number + '.zip')
        # return True

    def alter(self, file, old_str, new_str):
        """
        替换文件中的字符串
        :param file:文件名
        :param old_str:就字符串
        :param new_str:新字符串
        :return:
        """
        file_data = ""
        with open(file, "r", encoding="utf-8") as f:
            for line in f:
                if old_str in line:
                    line = line.replace(old_str, new_str)
                file_data += line
        with open(file, "w", encoding="utf-8") as f:
            f.write(file_data)

    def notification(self, order_number, rate):
        info = db.query(report_info).filter_by(order_number=order_number).first()
        user_info = db.query(User).filter_by(id=info.user).first()
        if user_info.gzh_open_id != '':
            notification = Notification()
            notification_title = info.title[0:8] + '...'
            notification_rate = rate + '%'
            notification.ReportCompletedNotification(user_info.gzh_open_id, notification_title, info.create_datetime,
                                                     notification_rate)

    def logistics(self, order_number):
        shop_token = {
            'samereport教育旗舰店': 'TbAldszyw2zfa35ttemzxhbh2zkx27x6mabxssreswt2vkxgxt',
            '正才教育专营店': 'TbAldsa4hc3vsabbpebnyypp43g5n8yss9kpuyyx4yct7w68z5',
        }
        order_numbers = db.query(orders_info).filter_by(order_number=order_number).all()
        for order in order_numbers:
            shop_info = db.query(taobao_orders).filter_by(order_number=order.taobao_orders).first()
            if shop_info:
                if shop_info.order_number in ['839843905366842610', '836876003067671953']:
                    return False
                shop_name = shop_info.shop
                if shop_name in list(shop_token.keys()):
                    token = shop_token[shop_name]
                    tids = []
                    for item in order_numbers:
                        tids.append(item.taobao_orders)
                    Logistics = Logistics_Dummy_Send(','.join(tids), token)
                    Logistics.validate_tid()


def run():
    db = RedisClient()
    while True:
        order_number = db.get_order_number
        try:
            if order_number:
                print(order_number)
                if order_number[0] == '9':
                    bot = MakeReport()
                    bot.makeLayuiReport(order_number)
                if order_number[0] == '8':
                    bot = MakeDocumentReport()
                    bot.makeLayuiReport(order_number)
            else:
                time.sleep(3)
        except Exception as e:
            print(e)
            db.push_order_number(order_number)
            time.sleep(3)


def run_test():
    order_number = '991721240338396'
    if order_number:
        if order_number[0] == '9':
            bot = MakeReport()
            bot.makeLayuiReport(order_number)
        if order_number[0] == '8':
            bot = MakeDocumentReport()
            bot.makeLayuiReport(order_number)


if __name__ == '__main__':
    run_test()
